import { CCFloat, CCInteger, Node, Director, director, Tween, tween, _decorator } from 'cc';
import { EDITOR } from 'cc/env';
import { ActionManager } from './ActionManager';
import { ActionPropFloat, ActionPropVec3 } from './ActionProp';
import { ActionPropHandler } from './ActionPropHandler';
import { BaseAction } from './BaseAction';
import Tools from './Tools';
import { AcitonType, Easing } from './Values';
const { ccclass, property, executeInEditMode } = _decorator;

@ccclass('Action')
@executeInEditMode(true)
export class Action extends BaseAction {
    // 动作属性值
    @property({ type: ActionPropFloat })
    public opacityProp = new ActionPropFloat();
    @property({ type: ActionPropVec3 })
    public positionProp = new ActionPropVec3();
    @property({ type: ActionPropVec3 })
    public scaleProp = new ActionPropVec3();
    @property({ type: ActionPropFloat })
    public angleProp = new ActionPropFloat();
    // 动作属性值结束

    @property({ type: CCFloat, tooltip: "动作时长" })
    public duration = 0;
    @property({ type: CCInteger, tooltip: "动作类型标记" })
    public actionFlag = 0;

    @property({ tooltip: "动作完成后重置" })
    public reset = false;
    @property({ type: Easing, tooltip: "动作缓动函数" })
    public easing: Easing = Easing.linear;

    // 属性值记录
    public propRecord: object = {};
    private finishCallback: Function;
    private beforeStartAction: Function;

    onLoad() {
        if (EDITOR) {
            // 使Tween系统可以在编辑器中运行
            director.getSystem("TWEEN")["override"] = function () {
                this._executeInEditMode = true;
            }
            director.getSystem("TWEEN")["override"]();
        } else {
            ActionManager.instance.onActionInit(this);
        }

        // update后记录初始属性值
        director.once(Director.EVENT_AFTER_UPDATE, this.recordProps, this);
    }

    // start() {
    // }

    /**
     * 记录属性值
     */
    recordProps() {
        let flag = 1, name = "";
        while ((name = AcitonType[flag])) {
            if (EDITOR || (this.actionFlag & flag)) {
                let handlerClass = ActionPropHandler.getHandlerClass(flag);
                let value = handlerClass.getPropValue(this);
                this.propRecord[name] = Tools.getClone(value);
            } else {
                this.propRecord[name] = null;
            }
            flag <<= 1;
        }
    }

    /**
     * 还原属性值
     */
    public recoverProps() {
        EDITOR && Tween.stopAllByTarget(this.node);

        let flag = 1, name = "";
        while ((name = AcitonType[flag])) {
            if (this.actionFlag & flag) {
                let value = this.propRecord[name];
                let handlerClass = ActionPropHandler.getHandlerClass(flag);
                handlerClass.setPropValue(this, value);
            }
            flag <<= 1;
        }

        for (let action of this.nextActions) {
            action.recoverProps();
        }
    }

    /**
     * 播放动画
     */
    public playAction(callback?: Function, beforeStartAction?: Function) {
        this.finishCallback = callback;

        this.beforeStartAction = beforeStartAction;
        if (this.beforeStartAction) {
            this.beforeStartAction(this);
        }

        this.setPropToStartValue();

        let tweenEntity = tween(this.node);
        if (this.delay > 0) {
            if (EDITOR) {
                // 编辑器下delay需要焦点才能生效，使用setTimeout代替delay。
                setTimeout(() => {
                    this.play(tweenEntity);
                    director.getSystem("TWEEN").update(0);
                }, this.delay * 1000);
                return;
            } else {
                tweenEntity.delay(this.delay);
            }
        }

        this.play(tweenEntity);
    }

    /**
     * 播放
     * @param tweenEntity 
     */
    private play(tweenEntity: Tween<Node>) {
        ActionPropHandler.handleTween(tweenEntity, this);

        tweenEntity.call(this.onPlayFinish.bind(this));

        tweenEntity.start();
    }

    /**
     * 将节点属性重置到初始值
     */
    public setPropToStartValue() {
        ActionPropHandler.resetToStartValue(this);

        for (let action of this.nextActions) {
            action.setPropToStartValue();
        }
    }

    /**
     * 播放完毕回调
     */
    onPlayFinish() {
        // 触发后续action的播放
        for (let action of this.nextActions) {
            action.playAction(this.finishCallback);
        }

        if (EDITOR) {
            this.onEventPlayFinish();
        } else {
            if (this.finishCallback) {
                this.finishCallback(this);
            }

            this.finishCallback = undefined;
            this.beforeStartAction = undefined;
        }
    }

    /**
     * 整个事件序列播放完毕的回调
     */
    public onEventPlayFinish() {
        if (this.reset) {
            this.recoverProps();
            for (let action of this.nextActions) {
                action.onEventPlayFinish();
            }
        }

        this.finishCallback = undefined;
        this.beforeStartAction = undefined;
    }
}